package com.shenhangye.pushlive.render

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.SurfaceTexture
import android.opengl.GLES11Ext

import android.opengl.GLES30.GL_COLOR_BUFFER_BIT
import android.opengl.GLES30.GL_DEPTH_BUFFER_BIT
import android.opengl.GLES30.GL_STENCIL_BUFFER_BIT
import android.opengl.GLES30.glClear
import android.opengl.GLES30.glClearColor
import android.opengl.GLES30.glEnableVertexAttribArray
import android.opengl.GLES30.glGetError
import android.opengl.GLES30.glUniformMatrix4fv
import android.opengl.GLES30
import android.opengl.GLSurfaceView
import android.opengl.Matrix
import android.util.Log
import android.view.Surface
import android.view.ViewGroup
import com.shenhangye.pushlive.R
import com.shenhangye.pushlive.camera.Camera2FrameCallback
import com.shenhangye.pushlive.camera.Camera2Wrapper
import com.shenhangye.pushlive.camera.CameraUtil.getFitInScreenSize
import com.shenhangye.pushlive.opengl.openglutil
import com.shenhangye.pushlive.opengl.openglutil.checkGlError
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import java.nio.FloatBuffer
import java.nio.IntBuffer
import javax.microedition.khronos.egl.EGLConfig
import javax.microedition.khronos.opengles.GL
import javax.microedition.khronos.opengles.GL10
import kotlin.math.max

class CameraRender(var context:Context,var mGLSurfaceView:GLSurfaceView):GLSurfaceView.Renderer {
    var program =0

    var mCamera2Wrapper:Camera2Wrapper?=null



//    1.0f, 1.0f,
//    0.0f, 1.0f,
    var vertex_position= floatArrayOf(
        -1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
        1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
        -1.0f, 1.0f, 0.0f,  0.0f, 1.0f,
       1.0f, 1.0f, 0.0f, 1.0f, 1.0f
    )

    var element_position= intArrayOf(
        0,1,2,
        1,2,3
    )



    var vao = intArrayOf(1)
    var vbo = intArrayOf(1)
    var ebo = intArrayOf(1)


    val vertex_buffer: FloatBuffer by lazy{
        openglutil.createFloatBuffer(vertex_position)
    }

    val element:IntBuffer by lazy{
        openglutil.createIntBuffer(element_position)
    }



    var oes=IntArray(1)




    var maxt=0
    private  val TAG = "CameraRender"
    var mSurfaceTexture:SurfaceTexture?=null
    override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {



        mCamera2Wrapper= Camera2Wrapper(context,object : Camera2FrameCallback{
            override fun onPreviewFrame(data: ByteArray?, width: Int, height: Int) {

            }

            override fun onCaptureFrame(data: ByteArray?, width: Int, height: Int) {

            }

        })
        GlobalScope.launch (Dispatchers.Main){


        val displayMetrics =context.resources.displayMetrics;
        val widthScreen = displayMetrics.widthPixels;
        val heightScreen = displayMetrics.heightPixels;
        mCamera2Wrapper?.previewSize?.let {
            Log.e(TAG,"previewSize"+it.width+"---"+it.height)
            getFitInScreenSize(it.width,it.height,widthScreen,heightScreen).apply {
                Log.e(TAG, "$width--surfaceCreated-$height")
//                setAspectRatio(width,height)
                val lp: ViewGroup.LayoutParams = mGLSurfaceView.layoutParams
                lp.width = width // required width
                lp.height = height // required height
                mGLSurfaceView.setLayoutParams(lp)
            }
        }
        }
        program=openglutil.createProgram(context, R.raw.camera_vert, R.raw.camera_fra);

          maxt=GLES30.glGetUniformLocation(program,"mtx")



        GLES30.glGenVertexArrays(vao.size,vao,0)
        GLES30.glGenBuffers(vbo.size,vbo,0)
        GLES30.glBindVertexArray(vao[0])
        GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER,vbo[0])
        GLES30.glBufferData(
            GLES30.GL_ARRAY_BUFFER,
            vertex_buffer.capacity() * 4,
            vertex_buffer,
            GLES30.GL_STATIC_DRAW
        )

        vertex_buffer.position(0)
        GLES30.glVertexAttribPointer(0,3,
            GLES30.GL_FLOAT,false,4*5,0)
        glEnableVertexAttribArray(0)

        vertex_buffer.position(3)
        GLES30.glVertexAttribPointer(1,2,
            GLES30.GL_FLOAT,false,4*5,3*4)
        glEnableVertexAttribArray(1)

        GLES30.glGenBuffers(ebo.size,ebo,0)
        GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER,ebo[0])
        GLES30.glBufferData(GLES30.GL_ELEMENT_ARRAY_BUFFER,element.capacity()*4,element,GLES30.GL_STATIC_DRAW)

//        openglutil.createTexture(texture,context)

        GLES30.glBindVertexArray(GLES30.GL_NONE)
        GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER,GLES30.GL_NONE)
        openglutil.createOes(oes)
        mSurfaceTexture =SurfaceTexture(oes[0])
        Log.e(TAG,oes[0].toString()+"oes");
        mSurfaceTexture?.setOnFrameAvailableListener {
            mGLSurfaceView.requestRender()
        }

        mCamera2Wrapper?.startCamera(mSurfaceTexture)
    }

    override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
        GLES30.glViewport(0,0,width,height)
    }
    var mtx= FloatArray(16)
    override fun onDrawFrame(gl: GL10?) {
        checkGlError("glBindTextu222223222re23333232323232")
        glClear(
            GL_STENCIL_BUFFER_BIT or GL_COLOR_BUFFER_BIT
                or GL_DEPTH_BUFFER_BIT
        )
        mSurfaceTexture?.updateTexImage()
//
//        Matrix.setIdentityM(mtx,0)
        mSurfaceTexture?.getTransformMatrix(mtx)

//          Matrix.rotateM(mtx,0,90,0,0)

        GLES30.glUseProgram(program)
        GLES30.glActiveTexture(GLES30.GL_TEXTURE0)
        GLES30.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,oes[0])
        GLES30.glUniformMatrix4fv(maxt,1,false,mtx,0)
        GLES30.glBindVertexArray(vao[0])
        GLES30.glDrawElements (GLES30.GL_TRIANGLE_STRIP, 6, GLES30.GL_UNSIGNED_INT,0);
        GLES30.glUseProgram (GLES30.GL_NONE);
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D,GLES30.GL_NONE)
    }
}